package com.ruoyi.dynamic.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.core.constant.SecurityConstants;
import com.ruoyi.common.core.constant.UserBalanceConstants;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.enums.CacheKey;
import com.ruoyi.common.core.pojo.result.PageUtils;
import com.ruoyi.common.core.pojo.result.Pages;
import com.ruoyi.common.core.utils.CollectionUtils;
import com.ruoyi.common.core.utils.CommonUtils;
import com.ruoyi.common.core.utils.DateUtils;
import com.ruoyi.common.redis.cache.CacheTemplate;
import com.ruoyi.dynamic.mapper.LuckyBagMapper;
import com.ruoyi.dynamic.model.constant.DynamicConstant;
import com.ruoyi.dynamic.model.constant.RoomChatRoomKvConstant;
import com.ruoyi.dynamic.model.pojo.entity.LuckyBag;
import com.ruoyi.dynamic.model.pojo.entity.LuckyBagComment;
import com.ruoyi.dynamic.model.pojo.entity.LuckyBagUser;
import com.ruoyi.dynamic.model.pojo.entity.Room;
import com.ruoyi.dynamic.model.pojo.request.app.*;
import com.ruoyi.dynamic.model.pojo.request.crm.CrmLuckBagCheckRequest;
import com.ruoyi.dynamic.model.pojo.result.app.AppLuckyBagInfoResult;
import com.ruoyi.dynamic.model.pojo.result.app.AppLuckyBakSuccessResult;
import com.ruoyi.dynamic.service.*;
import com.ruoyi.system.api.RemoteAppUserService;
import com.ruoyi.system.api.model.request.AppUserBalanceAocRequest;
import com.ruoyi.system.api.model.request.AppUserBalanceBatchOpetRequest;
import com.ruoyi.system.api.model.request.AppUserBalanceOpetRequest;
import com.ruoyi.system.api.model.user.AppUser;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;


@Service
public class LuckyBagServiceImpl extends ServiceImpl<LuckyBagMapper, LuckyBag> implements ILuckyBagService {
    @Autowired
    private IRoomService iRoomService;
    @Autowired
    private IMessageService iMessageService;
    @Autowired
    private ILuckyBagCommentService luckyBagCommentService;
    @Autowired
    private ILuckyBagUserService luckyBagUserService;
    @Autowired
    private RemoteAppUserService remoteAppUserService;
    @Autowired
    private IRoomShareRecordService iRoomShareRecordService;
    @Autowired
    private IRoomQuizRecordService iRoomQuizRecordService;
    @Autowired
    private IRoomSingService iRoomSingService;


    @Override
    public boolean release(AppCreateLuckBagRequest request, Long userId) {
        Room verify = iRoomService.verify(request.getRoomId());
        Assert.isTrue(verify.getUserId().equals(userId), "需房主发布福袋!");
        Assert.isTrue(verify(request.getRoomId(), userId) == 0, "您有发布的福袋正在审核中 请稍后再试");
        if (request.getPartWay().equals(DynamicConstant.BagPartWay.DAN)) {
            Assert.isTrue(StringUtils.hasText(request.getDanmuContent()), "弹幕内容不能为空");
        }
        BigDecimal totalMoney = BigDecimal.valueOf(request.getWinnerNum()).multiply(request.getLuckyBagMoney());

        AppUserBalanceOpetRequest opetRequest = new AppUserBalanceOpetRequest();
        opetRequest.setBalTypel(UserBalanceConstants.BalanceType.balance);
        opetRequest.setContent("发布福袋扣除:");
        opetRequest.setMoney(totalMoney);
        opetRequest.setType(UserBalanceConstants.Type.Zhi);
        opetRequest.setUserId(userId);
        R<Boolean> booleanR = remoteAppUserService.docBalance(opetRequest, SecurityConstants.APP);
        Assert.isTrue(booleanR.getCode() == 2000, booleanR.getmessage());

        LuckyBag luckyBag = new LuckyBag();
        BeanUtils.copyProperties(request, luckyBag);
        luckyBag.setCreateTime(new Date());
        luckyBag.setUserId(userId);
        luckyBag.setStatus(DynamicConstant.CheckStatus.NO);
        luckyBag.setIsTemplate(request.getIsTemplate());
        luckyBag.setTotalMoney(totalMoney);
        return save(luckyBag);
    }

    @Override
    public Long verify(Long roomId, Long userId) {
        return lambdaQuery()
                .eq(LuckyBag::getRoomId, roomId)
                .eq(LuckyBag::getUserId, userId)
                .eq(LuckyBag::getStatus, DynamicConstant.RoomStatus.NO)
                .count()
                ;
    }

    @Override
    public LuckyBag verifyById(Long id) {
        Optional<LuckyBag> luckyBag = lambdaQuery().eq(LuckyBag::getId, id).oneOpt();
        Assert.isTrue(luckyBag.isPresent(), "此福袋不存在");
        return luckyBag.get();
    }

    @Override
    public boolean check(CrmLuckBagCheckRequest request) {
        LuckyBag luckyBag = verifyById(request.getId());
        Assert.isTrue(luckyBag.getStatus().equals(DynamicConstant.CheckStatus.NO), "此福袋已审核");

        Calendar instance = Calendar.getInstance();
        instance.setTime(new Date());
        instance.add(Calendar.SECOND, luckyBag.getCountDownTime());
        luckyBag.setStatus(request.getStatus());
        luckyBag.setEndTime(instance.getTime());
        updateById(luckyBag);

        if (luckyBag.getStatus().equals(DynamicConstant.CheckStatus.YES)) {
            Room verify = iRoomService.verify(luckyBag.getRoomId());

            String key = CacheKey.LUCKY_BAG_INFO.getKey(String.valueOf(luckyBag.getId()));
            CacheTemplate.setCache(key, luckyBag, 30L, TimeUnit.MINUTES);

            //发送redis过期事件
            CacheTemplate.setCacheExpire(RoomChatRoomKvConstant.ROOM_LUCK_BAG_ID + luckyBag.getId(), luckyBag.getId(), Long.valueOf(luckyBag.getCountDownTime()), TimeUnit.SECONDS);

            iMessageService.setRoomChatRoomAttr(verify.getGroupId(), verify.getUserId().toString(), RoomChatRoomKvConstant.ROOM_LUCK_BAG, JSONObject.toJSONString(luckyBag), 0, "", "");


        }
        return true;
    }

    @Override
    public AppLuckyBagInfoResult info(Long id, Long userId) {
        LuckyBag luckyBag = verifyById(id);
        return getInfo(luckyBag, userId);
    }

    AppLuckyBagInfoResult getInfo(LuckyBag luckyBag, Long userId) {
        return AppLuckyBagInfoResult.builder()
                .id(luckyBag.getId())
                .countDownTime(luckyBag.getCountDownTime())
                .danmuContent(luckyBag.getDanmuContent())
                .endTime(luckyBag.getEndTime())
                .residueTime(DateUtils.timeBySec(luckyBag.getEndTime(), new Date()))
                .isPart(luckyBag.getIsPart())
                .luckyBagMoney(luckyBag.getLuckyBagMoney())
                .name(luckyBag.getName())
                .partWay(luckyBag.getPartWay())
                .refuseMemo(luckyBag.getRefuseMemo())
                .roomId(luckyBag.getRoomId())
                .userId(luckyBag.getUserId())
                .status(luckyBag.getStatus())
                .luckyBagUsers(luckyBagUserService.getUserListId(luckyBag.getId()))
                .winnerNum(luckyBag.getWinnerNum())
                .isJoin(luckyBagUserService.isJoinByUser(luckyBag.getId(), userId))
                .isReach(this.isReachByUser(luckyBag.getId(), userId, luckyBag.getRoomId()))
                .build()
                ;
    }


    @Override
    public Integer isReachByUserId(LuckyBag luckyBag) {

        if (luckyBag.getPartWay().equals(DynamicConstant.BagPartWay.DAN)) {
            //判断弹幕是否发过
        }


        return null;
    }


    @Override
    public boolean comment(AppLuckyBagCommentRequest request, Long userId) {
        Room verify = iRoomService.verify(request.getRoomId());
        LuckyBag luckyBag = verifyById(request.getLuckyBagId());
        Assert.isTrue(luckyBag.getStatus().equals(DynamicConstant.CheckStatus.YES), "此福袋活动已结束");
        Long count = luckyBagCommentService.lambdaQuery()
                .eq(LuckyBagComment::getRoomId, request.getRoomId())
                .eq(LuckyBagComment::getLuckyBagId, request.getLuckyBagId())
                .eq(LuckyBagComment::getUserId, userId)
                .count();
        Assert.isTrue(count == 0, "您已参与此福袋请勿重复参与");

        if (luckyBag.getIsPart().equals(DynamicConstant.CheckStatus.YES)) {
            //判断是否是粉丝
            R<Integer> myFens = remoteAppUserService.isMyFens(verify.getUserId(), userId, SecurityConstants.APP);
            Assert.isTrue(myFens.getData() > 0, "您不是主播粉丝无法参与");
        }

        if (luckyBag.getPartWay().equals(DynamicConstant.BagPartWay.DAN)) {
            Assert.isTrue(request.getContent().equals(luckyBag.getDanmuContent()), "您评论的不符合参与条件");
        } else {
            Assert.isTrue(this.isReachByUser(luckyBag.getId(), userId, verify.getId()), "不符合参与条件");
        }

        R<AppUser> userInfo = remoteAppUserService.getUserInfo(userId, SecurityConstants.APP);
        AppUser data = userInfo.getData();

        if (luckyBag.getPartWay().equals(DynamicConstant.BagPartWay.DAN)) {
            LuckyBagComment comment = new LuckyBagComment();
            comment.setUserId(userId);
            comment.setContent(request.getContent());
            comment.setLuckyBagId(request.getLuckyBagId());
            comment.setRoomId(request.getRoomId());
            comment.setCreateTime(new Date());
            luckyBagCommentService.save(comment);
        }
        luckyBagUserService.addRecord(userId, request.getRoomId(), "", data.getNickName(), data.getPhoto(), luckyBag.getPartWay(), luckyBag.getId());
        return true;
    }

    @Override
    public Pages<LuckyBagUser> userListPage(AppLuckyBagUserSearchRequest request) {
        Page<LuckyBagUser> luckyBagUserPage = PageUtils.initPage(request, LuckyBagUser.class);
        Page<LuckyBagUser> page = luckyBagUserService.lambdaQuery()
                .eq(LuckyBagUser::getRoomId, request.getRoomId())
                .eq(LuckyBagUser::getLuckyBagId, request.getLuckyBagId())
                .eq(!CommonUtils.isNull(request.getIsWinner()), LuckyBagUser::getIsWinner, request.getIsWinner())
                .orderByDesc(LuckyBagUser::getCreateTime)
                .page(luckyBagUserPage);
        return PageUtils.pages(page);
    }

    @Override
    public boolean saveTem(AppRoomVoteMusicTemRequest request, Long userId) {
        LuckyBag luckyBag = verifyById(request.getId());
        luckyBag.setIsTemplate(DynamicConstant.CheckStatus.YES);
        luckyBag.setFromId(luckyBag.getId());
        return updateById(luckyBag);
    }

    @Override
    public Pages<AppLuckyBagInfoResult> listPage(AppLuckBagSearchRequest request, Long userId) {
        Page<LuckyBag> luckyBagPage = PageUtils.initPage(request, LuckyBag.class);

        Page<LuckyBag> page = lambdaQuery()
                .eq(request.isTemplate(), LuckyBag::getUserId, userId)
                .eq(request.isTemplate(), LuckyBag::getIsTemplate, DynamicConstant.CheckStatus.YES)
                .eq(!CommonUtils.isNull(request.getRoomId()), LuckyBag::getRoomId, request.getRoomId())
                .page(luckyBagPage);

        List<AppLuckyBagInfoResult> results = CollectionUtils.emptyList();
        for (LuckyBag record : page.getRecords()) {
            results.add(getInfo(record, userId));
        }
        return PageUtils.pages(page, results);
    }

    @Override
    public boolean updateLuck(AppCreateLuckBagRequest request, Long userId) {
        LuckyBag luckyBag = verifyById(request.getId());
        Assert.isTrue(luckyBag.getUserId().equals(userId), "您无权编辑福袋");
        Assert.isTrue(!luckyBag.getStatus().equals(DynamicConstant.CheckStatus.YES), "此福袋正在进行中无法编辑");
        BeanUtils.copyProperties(request, luckyBag);
        luckyBag.setStatus(DynamicConstant.CheckStatus.NO);
        return updateById(luckyBag);
    }

    @Override
    public void over(String id, Integer status) {
        LuckyBag luckyBag = verifyById(Long.valueOf(id));
        Room verify = iRoomService.verify(luckyBag.getRoomId());
        if (status.equals(DynamicConstant.CheckStatus.FENG) && luckyBag.getStatus().equals(DynamicConstant.CheckStatus.YES)) {
            luckyBag.setStatus(status);
            //发送redis过期事件
            CacheTemplate.clear(RoomChatRoomKvConstant.ROOM_LUCK_BAG_ID + luckyBag.getId());

        }
        updateById(luckyBag);
        iMessageService.setRoomChatRoomAttr(verify.getGroupId(), verify.getUserId().toString(), RoomChatRoomKvConstant.ROOM_LUCK_BAG, JSONObject.toJSONString(luckyBag), 0, "", "");

        //获取参与人数
        List<LuckyBagUser> list = luckyBagUserService.getUserListId(luckyBag.getId());

        Set<Long> successIds = CollectionUtils.emptySet();
        Set<Long> failIds = CollectionUtils.emptySet();
        if (!list.isEmpty()) {
            if (list.size() < luckyBag.getWinnerNum()) {
                //参与人数小于中奖人数直接给这几个人发放钻石
                successIds = list.stream().map(LuckyBagUser::getUserId).collect(Collectors.toSet());
                BigDecimal moeny = BigDecimal.valueOf(luckyBag.getWinnerNum() - list.size()).multiply(luckyBag.getLuckyBagMoney());

                AppUserBalanceOpetRequest opetRequest = new AppUserBalanceOpetRequest();
                opetRequest.setUserId(luckyBag.getUserId());
                opetRequest.setType(UserBalanceConstants.Type.Ru);
                opetRequest.setMoney(moeny);
                opetRequest.setContent("福袋为满足中奖人数退还剩余金额:" + moeny);
                opetRequest.setBalTypel(UserBalanceConstants.BalanceType.balance);
                //退还的金额
                R<Boolean> booleanR = remoteAppUserService.aocBalance(opetRequest, SecurityConstants.APP);

            } else {
                Collections.shuffle(list);
                List<LuckyBagUser> subList = list.subList(0, luckyBag.getWinnerNum());
                successIds = subList.stream().map(LuckyBagUser::getUserId).collect(Collectors.toSet());
                List<LuckyBagUser> failList = list.subList(luckyBag.getWinnerNum(), list.size());
                failIds = failList.stream().map(LuckyBagUser::getUserId).collect(Collectors.toSet());
            }
            if (!successIds.isEmpty()) {
                luckyBagUserService.lambdaUpdate()
                        .eq(LuckyBagUser::getLuckyBagId, luckyBag.getId())
                        .in(LuckyBagUser::getUserId, successIds)
                        .set(LuckyBagUser::getIsWinner, DynamicConstant.CheckStatus.YES)
                        .set(LuckyBagUser::getMoney, luckyBag.getLuckyBagMoney())
                        .update();

                List<AppUserBalanceAocRequest> requests = successIds.stream().map(res -> {
                    AppUserBalanceAocRequest request = new AppUserBalanceAocRequest();
                    request.setMoney(luckyBag.getLuckyBagMoney());
                    request.setRemark(luckyBag.getName() + ":福袋中奖获得");
                    request.setUserId(res);
                    return request;
                }).collect(Collectors.toList());
                AppUserBalanceBatchOpetRequest batchOpetRequest = new AppUserBalanceBatchOpetRequest();
                batchOpetRequest.setType(UserBalanceConstants.BalanceType.balance);
                batchOpetRequest.setBalTypel(UserBalanceConstants.BalanceType.balance);
                batchOpetRequest.setRequests(requests);
                remoteAppUserService.aocBalanceByBatch(batchOpetRequest, SecurityConstants.APP);
            }


            AppLuckyBakSuccessResult build = AppLuckyBakSuccessResult.builder()
                    .failIds(failIds)
                    .successIds(successIds)
                    .id(luckyBag.getId())
                    .name(luckyBag.getName())
                    .luckyBagMoney(luckyBag.getLuckyBagMoney())
                    .build();


            iMessageService.setRoomChatRoomAttr(verify.getGroupId(), verify.getUserId().toString(), RoomChatRoomKvConstant.ROOM_LUCK_BAG_RESULT,
                    JSONObject.toJSONString(build), 0, "", ""
            );

        }
    }

    @Override
    public boolean isReachByUser(Long id, Long userId, Long roomId) {
        LuckyBag luckyBag = verifyById(id);
        boolean userSing = false;
        if (luckyBag.getPartWay().equals(DynamicConstant.BagPartWay.DAN)) {
            userSing = luckyBagUserService.isJoinByUser(id, userId);
        } else if (luckyBag.getPartWay().equals(DynamicConstant.BagPartWay.SHARE)) {
            userSing = iRoomShareRecordService.isShareByUser(roomId, userId);
        } else if (luckyBag.getPartWay().equals(DynamicConstant.BagPartWay.ASK)) {
            userSing = iRoomQuizRecordService.isUserQuiz(roomId, userId);
        } else if (luckyBag.getPartWay().equals(DynamicConstant.BagPartWay.MUSIC)) {
            userSing = iRoomSingService.isUserSing(roomId, userId);
        }
        return userSing;
    }
}
